#include "USBHIDMouse.h"
#include "USBHIDKeyboard.h"
USBHIDMouse Mouse;
USBHIDKeyboard Keyboard;
#include "esp_partition.h"
#include "esp_ota_ops.h"
const esp_partition_t* partition0 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
const esp_partition_t* partition1 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
const int PC_SWITCH = 3; // 替换为你连接的引脚号
const int PC_V = 39; // 替换为你连接的引脚号

#define RXD1 35
#define TXD1 37

#define POWER_EVT_START 247

#define KB_EVT_START 248
#define MOUSE_EVT_START 249
#define KEY_SEQUENCE_EVT_START 250
#define EVT_END 251
#define KB_EVT_TYPE_RESET 3
#define PARTITION_0 0
#define PARTITION_1 1
#define PC_POWER_ON 2
#define PC_POWER_OFF 3
#define PC_POWER_LONG 4
#define PC_POWER_S 5
#define PC_POWER_MODE 6

#define KB_EVT_TYPE_KEYDOWN 1
#define KB_EVT_TYPE_KEYUP 2
#define KB_EVT_TYPE_RESET 3

#define MOUSE_EVT_TYPE_MOVE 1
#define MOUSE_EVT_TYPE_LEFT_DOWN 2
#define MOUSE_EVT_TYPE_LEFT_UP 3
#define MOUSE_EVT_TYPE_MIDDLE_DOWN 4
#define MOUSE_EVT_TYPE_MIDDLE_UP 5
#define MOUSE_EVT_TYPE_RIGHT_DOWN 6
#define MOUSE_EVT_TYPE_RIGHT_UP 7
#define MOUSE_EVT_TYPE_WHEEL 8
#define MOUSE_EVT_TYPE_RESET 9
#define MOUSE_EVT_TYPE_CONFIG_MOVE_FACTOR 10
#define PC_POWER 11
#define PC_VOLTAGE 12
#define R_BUF_LEN 32
int pinVoltage = 0;
int rBuf[R_BUF_LEN];
int rBufCursor = 0;
int mouseMoveFactor = 1;
uint8_t buttons = 0;
uint8_t scan_code_map[256] = {0};
uint8_t count = 0;
uint8_t keycode[6] = {0};
uint8_t modifier = 0;


void setup() {
  pinMode(PC_SWITCH, OUTPUT);
  digitalWrite(PC_SWITCH, LOW);
  pinMode(PC_V,INPUT);

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  Keyboard.begin();
  Mouse.begin();
  Serial1.begin(115200, SERIAL_8N1, RXD1, TXD1);

}

void parse_r_buf() {
  if (rBuf[0] == KB_EVT_START && rBufCursor == 3) {
    switch (rBuf[1]) {
       case KB_EVT_TYPE_KEYDOWN:
        Keyboard.press(rBuf[2]);
        break;
       case KB_EVT_TYPE_KEYUP:
        Keyboard.release(rBuf[2]);
        break;
       case KB_EVT_TYPE_RESET:
        Keyboard.releaseAll();
        break;
    }
  }

  if (rBuf[0] == MOUSE_EVT_START && rBufCursor == 4) {
    switch (rBuf[1]) {
       case MOUSE_EVT_TYPE_MOVE:
        Mouse.move(mouseMoveFactor * (rBuf[2] - 120), mouseMoveFactor * (rBuf[3] - 120), 0);
        break;
       case MOUSE_EVT_TYPE_LEFT_DOWN:
        Mouse.press(MOUSE_LEFT);
        break;
       case MOUSE_EVT_TYPE_LEFT_UP:
        Mouse.release(MOUSE_LEFT);
        break;
       case MOUSE_EVT_TYPE_RIGHT_DOWN:
        Mouse.press(MOUSE_RIGHT);
        break;
       case MOUSE_EVT_TYPE_RIGHT_UP:
        Mouse.release(MOUSE_RIGHT);
        break;
       case MOUSE_EVT_TYPE_MIDDLE_DOWN:
        Mouse.press(MOUSE_MIDDLE);
        break;
       case MOUSE_EVT_TYPE_MIDDLE_UP:
        Mouse.release(MOUSE_MIDDLE);
        break;
       case MOUSE_EVT_TYPE_WHEEL:
        Mouse.move(0, 0, rBuf[2] - 120);
        break;
       case MOUSE_EVT_TYPE_RESET:
        Mouse.release(MOUSE_LEFT);
        Mouse.release(MOUSE_RIGHT);
        Mouse.release(MOUSE_MIDDLE);
        break;
       case MOUSE_EVT_TYPE_CONFIG_MOVE_FACTOR:
        mouseMoveFactor = rBuf[2];
    }
  }

 if (rBuf[0] == POWER_EVT_START && rBufCursor == 2) {
    switch (rBuf[1]) {
      case PARTITION_0:
        esp_ota_set_boot_partition(partition0);
        esp_restart();
        break;
      case PARTITION_1:
        esp_ota_set_boot_partition(partition1);
        esp_restart();
        break;
      case PC_POWER_ON:
        // 发送高电平1.5秒到ESP32的pin13
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage != HIGH) {
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(1000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);


            } 
        break;
      case PC_POWER_OFF:
        // 发送高电平1.秒到ESP32的pin13
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage == HIGH) {
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(1000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);


            } 
        break;
                
      case PC_POWER_LONG:
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage == HIGH) {
            // 发送高电平5秒到ESP32的pin13
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(5000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);

            } 
        break;
      case PC_POWER_S:
        // 测量PC_V电压是高电平还是低电平
        pinVoltage = digitalRead(PC_V);
        // 判断PC_V的电压状态并在串口1上打印相应的消息
        if (pinVoltage == HIGH) {
          Serial1.println("poweron");
        } else if (pinVoltage == LOW) {
          Serial1.println("poweroff");
        }
        break;
      case PC_POWER_MODE:
        Serial1.println("mode0");
        break;
    }
  }
  if (rBuf[0] == KEY_SEQUENCE_EVT_START && rBufCursor > 1) {
      Keyboard.releaseAll();
      for (int i = 1; i < rBufCursor; i += 1) {
          Keyboard.write(rBuf[i]);
      }
    }
}

void reset_r_buf() {
   rBufCursor = 0;
   rBuf[0] = 0;
}

void loop() {
  int curVal;
  while (Serial1.available() > 0) {
    curVal = Serial1.read();
    
    if (curVal == EVT_END) {
      parse_r_buf();
      // blink();
      reset_r_buf();
    } else {
      if (rBufCursor == 0) {
        if (curVal == POWER_EVT_START || KB_EVT_START || curVal == MOUSE_EVT_START || curVal == KEY_SEQUENCE_EVT_START) {
          rBuf[rBufCursor] = curVal;
          rBufCursor += 1;
        }
      } else {
        if (rBufCursor < R_BUF_LEN) {
           rBuf[rBufCursor] = curVal;
           rBufCursor += 1;
        } else {
          // overflow, reset rBuf
          rBuf[0] = 0;
        }
      }
    }
  }
}